#include "labyrinth.h"

#include <stdio.h>
#include <stdlib.h>

int** allocate_field(int size)
{
    int** result;
    int i;
    
    result = (int**)malloc(sizeof(int*) * size);
    for(i = 0; i < size; i++)
        result[i] = (int*)calloc(size, sizeof(int));
        
    return result;
}

void free_field(int** field, int size)
{
    int i;
    
    for(i = 0; i < size; i++)
        free(field[i]);
    free(field);
}

void generate_coridor(int** field, int x0, int y0, int size, int type, int style)  //total govnokod detected
{
    int i, j, n, k;
    int *X;
    //printf("%d %d, type: %d\n",x0,y0,type);
    X = (int*)malloc(sizeof(int) * size);
    n = 0;
    
    if(type == 0) {
        for(i = 0; i < size; i++)
            if((field[x0 - 1][y0 + i] == 1) && (field[x0 + 1][y0 + i] == 1)) {
                X[n] = i;
                n++;
            }
    } else {
        for(i = 0; i < size; i++)
            if((field[x0 + i][y0 - 1] == 1) && (field[x0 + i][y0 + 1] == 1)) {
                X[n] = i;
                n++;
            }
    }
    
    k = 1;
    if(style) {
        if(n != 1)
            k = rand() % (n - 1) + 1;
    }
        
    for(i = 0; i < k; i++) {
        j = rand() % n;
         if(type == 0)
            field[x0][y0 + X[j]] = 1;
        else field[x0 + X[j]][y0] = 1;
    }
    
    free(X);
}

void generate_fractal(int** field, struct topology *base, int x, int y, int style)
{
    int i, size;
    //printf("%d\n",base->depth);
    size = 0;
    for(i  = 0; i < base->depth + 1; i++)
            size = size * 2 + 1;
            
    if(base->depth > 0) {        
        generate_fractal(field, base->segments[0], x, y, style);
        generate_fractal(field, base->segments[1], x + size + 1, y, style);
        generate_fractal(field, base->segments[2], x, y + size + 1, style);
        generate_fractal(field, base->segments[3], x + size + 1, y + size + 1, style);
    }

    if(base->coridor[0])
        generate_coridor(field, x, y + size, size, 1, style);
    if(base->coridor[1])
        generate_coridor(field, x + size, y + size + 1, size, 0, style);
    if(base->coridor[2])
        generate_coridor(field, x + size + 1, y + size, size, 1, style);
    if(base->coridor[3])
        generate_coridor(field, x + size, y, size, 0, style);
}

int** convert_topology(struct topology *base, int style)
{
    int** result;
    int size, i, j;
    
    size = 0;    
    for(i  = 0; i < base->depth + 2; i++)
        size = size * 2 + 1;
        
    result = allocate_field(size);
    
    for(i = 0; i < size; i += 2)
        for(j = 0; j < size; j += 2)
            result[i][j] = 1;
            
    generate_fractal(result, base, 0, 0, style);
    return result;
}
